<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,
        body {
            height: 100%;
        }
    </style>
</head>

<body>
    <script>
        // 防抖在一段连续操作后，处理回调
        function debounce(fn, delay) {
            let timer = null
            return function () {
                let context = this
                let args = arguments
                clearTimeout(timer)
                timer = setTimeout(() => {
                    // 保证fn中this的指向为dom，并且保留参数
                    fn.apply(context, args)
                }, delay)
            }
        }
        // 立即执行
        function debounce1(fn, delay, immediate) {
            let timer = null
            return function (...args) {
                let context = this
                if (!timer) clearTimeout(timer)
                if (immediate) {
                    let isFirst = !timer
                    timer = setTimeout(() => {
                        !isFirst && fn.apply(context, args)
                        timer = null
                    }, delay)
                    if (isFirst) {
                        fn.apply(context, args)
                    }
                } else {
                    timer = setTimeout(() => {
                        fn.apply(context, args)
                        timer = null
                    }, delay)
                }
            }
        }
        function foo() {
            console.log('+++', this);
        }
        // 执行第一次和最后一次
        function debounce2(fn, delay, immediate) {
            let timer = null
            return function (...args) {
                let isFirst = !timer
                let that = this
                if (isFirst && immediate) {
                    fn.apply(this, args)
                }
                if (timer) clearTimeout(timer)
                timer = setTimeout(() => {
                    fn.apply(this, args)
                    timer = null
                }, delay)
            }
        }
        // 只执行第一次，这个只执行一次防抖好像没有意义
        function debounce3(fn, delay, immediate) {
            let timer = null
            return function (...args) {
                let isFirst = !timer
                let that = this
                if (isFirst && immediate) {
                    fn.apply(that, args)
                }
                if (timer) clearTimeout(timer)
                timer = setTimeout(() => {
                    timer = null
                }, delay)
            }
        }
        document.body.addEventListener('click', debounce2(foo, 2000, true))
    </script>
</body>

</html>